package com.jstyle.nordic_otas.nordic_otas_plugin;

import android.app.Activity;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;

import androidx.annotation.NonNull;

import java.io.File;

import io.flutter.Log;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import no.nordicsemi.android.dfu.DfuBaseService;
import no.nordicsemi.android.dfu.DfuProgressListener;
import no.nordicsemi.android.dfu.DfuServiceController;
import no.nordicsemi.android.dfu.DfuServiceInitiator;
import no.nordicsemi.android.dfu.DfuServiceListenerHelper;

/** NordicOtasPlugin */
public class NordicOtasPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware {
  private MethodChannel channel;

  private String filePath;
  private String firwmarePath;
  private String macAddress;
  private String deviceName;
  private Activity activity;
  private DfuServiceController serviceController;
  private Handler handler = new Handler(){
    @Override
    public void handleMessage(@NonNull Message msg) {
      super.handleMessage(msg);
      switch (msg.what){
        case 0:
          break;
        case 1:
          break;
      }

    }
  };
  private DfuProgressListener dfuProgressListener = new DfuProgressListener() {
    @Override
    public void onDeviceConnecting(@NonNull String s) {
//      Log.e("test","dfuProgressListener-onDeviceConnecting: " +s);
    }

    @Override
    public void onDeviceConnected(@NonNull String s) {
//      Log.e("test","dfuProgressListener-onDeviceConnected: " +s);
    }

    @Override
    public void onDfuProcessStarting(@NonNull String s) {
//      Log.e("test","dfuProgressListener-onDfuProcessStarting: " +s);
      sendMessage("1@0");
    }

    @Override
    public void onDfuProcessStarted(@NonNull String s) {
//      Log.e("test","dfuProgressListener-onDfuProcessStarted: " +s);
      sendMessage("2@0");
    }

    @Override
    public void onEnablingDfuMode(@NonNull String s) {
//      Log.e("test","dfuProgressListener-onEnablingDfuMode: " +s);
    }

    @Override
    public void onProgressChanged(@NonNull String s, int i, float v, float v1, int i1, int i2) {
//      Log.e("test","dfuProgressListener-onProgressChanged: " +i);
      sendMessage("3@"+ i);
    }

    @Override
    public void onFirmwareValidating(@NonNull String s) {
//      Log.e("test","dfuProgressListener-onFirmwareValidating: " +s);
    }

    @Override
    public void onDeviceDisconnecting(String s) {
//      Log.e("test","dfuProgressListener-onDeviceDisconnecting: " +s);
    }

    @Override
    public void onDeviceDisconnected(@NonNull String s) {
//      Log.e("test","dfuProgressListener-onDeviceDisconnected: " +s);
      sendMessage("6@0");
    }

    @Override
    public void onDfuCompleted(@NonNull String s) {
//      Log.e("test","dfuProgressListener-onDfuCompleted: " +s);
      sendMessage("5@0");
      DfuServiceListenerHelper.unregisterProgressListener(activity,dfuProgressListener);
    }

    @Override
    public void onDfuAborted(@NonNull String s) {
//      Log.e("test","dfuProgressListener-onDeviceDisconnected: " +s);
      sendMessage("4@0");
    }

    @Override
    public void onError(@NonNull String s, int i, int i1, String s1) {
//      Log.e("test","dfuProgressListener-onError: " +s);
      sendMessage("8@0");
    }
  };

  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
    channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "nordic_otas_plugin");
    channel.setMethodCallHandler(this);
  }

  @Override
  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
//    Log.e("test","onMethodCall-method: " + call.method);
    if (call.method.equals("getPlatformVersion")) {
      result.success("Android " + android.os.Build.VERSION.RELEASE);
    } else if(call.method.equals("setFilePath")){
      if(call.hasArgument("path")){
        filePath = call.argument("path");
      }
      setFilePath(filePath);
    } else if(call.method.equals("startAndroidOta")){
      if(call.hasArgument("address")){
        macAddress = call.argument("address");
      }
      if(call.hasArgument("name")){
        deviceName = call.argument("name");
      }
      activity.runOnUiThread(new Runnable() {
        @Override
        public void run() {
          startOta(deviceName,macAddress,firwmarePath);
        }
      });
    }else if(call.method.equals("notice")){
      result.success(notice());
    }else {
      result.notImplemented();
    }
  }


  private void setFilePath(String path){
//    Log.e("test","setFilePath: " + path);
    try{
      if(TextUtils.isEmpty(path)){
        sendMessage("7@0");
        return;
      }
      ZipUtils.upZipFile(path, ZipUtils.getFromPath(activity)+"ota/");
      File file = new File(ZipUtils.getFromPath(activity)+"ota/");
      if(!file.exists()){
        sendMessage("7@0");
        return;
      }
      File[] files = file.listFiles();
      for (int i = 0; i < files.length; i++) {
//      Log.e("test","fileName: " + files[i].getName());
        if(files[i].getName().contains("zip")){
          firwmarePath = files[i].getAbsolutePath();
        }
      }
    }catch (Exception e){
      sendMessage("7@0");
    }

  }

  private void sendMessage(String text) {
    handler.post(new Runnable() {
      @Override
      public void run() {
        channel.invokeMethod("sendMessage",text);
      }
    });
  }


  private boolean notice(){
    if(!NoticeUtils.isEnabledNotification(activity)){
      NoticeUtils.setting(activity);
      return false;
    }
    return true;
  }
  private void startOta(String name,String address,String path){
    if(TextUtils.isEmpty(name))return;
    if(TextUtils.isEmpty(address))return;
    if(TextUtils.isEmpty(path))return;
    DfuServiceListenerHelper.unregisterProgressListener(activity,dfuProgressListener);
    DfuServiceListenerHelper.registerProgressListener(activity,dfuProgressListener);
    Uri uri = Uri.parse("file:"+path);
    final DfuServiceInitiator initiator = new DfuServiceInitiator(address)
            .setDeviceName(name)
            .setKeepBond(false)
            .setForceDfu(false)
            .setPacketsReceiptNotificationsEnabled(Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
            .setPacketsReceiptNotificationsValue(DfuServiceInitiator.DEFAULT_PRN_VALUE)
            .setUnsafeExperimentalButtonlessServiceInSecureDfuEnabled(true);
    if(path.endsWith("zip")){
      initiator.setZip(uri,path);
    }else {
      initiator.setBinOrHex(DfuBaseService.TYPE_APPLICATION,uri,path);
    }
    serviceController = initiator.start(activity,DfuService.class);
  }

  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    channel.setMethodCallHandler(null);
    DfuServiceListenerHelper.unregisterProgressListener(activity,dfuProgressListener);
  }

  @Override
  public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
//    Log.e("test","onAttachedToActivity");
    activity = binding.getActivity();

  }

  @Override
  public void onDetachedFromActivityForConfigChanges() {

  }

  @Override
  public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {

  }

  @Override
  public void onDetachedFromActivity() {

  }
}
